package com.tsfyun.common.base.util;

import cn.hutool.core.util.ZipUtil;
import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
import com.tsfyun.common.base.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.util.Objects;

/**
 * @Description:
 * @since Created in 2020/4/20 12:08
 */
@Slf4j
public class XmlUtils {

    /**
     * 将对象直接转换成String类型的 XML输出
     *
     * @param obj
     * @return
     */
    public static String convertToXml(Object obj) {
        //创建输出流
        StringWriter sw = new StringWriter();
        try {
            // 利用jdk中自带的转换类实现
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            sw.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n    ");
            Marshaller marshaller = context.createMarshaller();
            // 格式化xml输出的格式
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                    Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            marshaller.marshal(obj,sw);
        } catch (JAXBException e) {
            log.error("转换成xml字符串异常",e);
            return null;
        }
        return sw.toString();
    }

    /**
     * 将对象根据路径转换成xml文件
     *
     * @param obj        对象
     * @param path       路径
     * @param fileName   文件名，不含文件后缀
     * @return
     */
    public static void convertToXml(Object obj, String path,String fileName) {
        FileWriter fw = null;
        try {
            // 利用jdk中自带的转换类实现
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            StringWriter stringWriter = new StringWriter();
            stringWriter.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n    ");
            Marshaller marshaller = context.createMarshaller();
            // 格式化xml输出的格式
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                    Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            marshaller.marshal(obj,stringWriter);
            String stringXml = stringWriter.toString();
            // 将对象转换成输出流形式的xml
            // 创建输出流
            File destFile = new File(path);
            if(!destFile.exists()) {
                destFile.mkdirs();
            }
            fw = new FileWriter(path + File.separator + fileName + ".xml");
            fw.write(stringXml);
        } catch (JAXBException | IOException e) {
            log.error("生成xml文件异常",e);
            throw new ServiceException("生成报文异常");
        } finally {
            if (null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 将对象根据路径转换成xml文件
     *
     * @param obj        对象
     * @param path       路径
     * @param fileName   文件名，不含文件后缀
     * @return
     */
    public static void convertToXmlWithReplace(Object obj, String path,String fileName,Boolean needReplace2Pre,String replaceVal) {
        FileWriter fw = null;
        try {
            // 利用jdk中自带的转换类实现
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            StringWriter stringWriter = new StringWriter();
            stringWriter.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n    ");
            Marshaller marshaller = context.createMarshaller();
            // 格式化xml输出的格式
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                    Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            marshaller.marshal(obj,stringWriter);
            String stringXml = stringWriter.toString();
            if(Objects.equals(needReplace2Pre,true)) {
                stringXml = stringXml.replace("urn:Declaration:datamodel:standard:CN:MT1401:1",replaceVal);
            }
            // 将对象转换成输出流形式的xml
            // 创建输出流
            File destFile = new File(path);
            if(!destFile.exists()) {
                destFile.mkdirs();
            }
            fw = new FileWriter(path + File.separator + fileName + ".xml");
            fw.write(stringXml);
        } catch (JAXBException | IOException e) {
            log.error("生成xml文件异常",e);
            throw new ServiceException("生成报文异常");
        } finally {
            if (null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 将对象根据路径转换成xml文件
     *
     * @param obj        对象
     * @param path       路径
     * @param fileName   文件名，不含文件后缀
     * @return
     */
    public static void convertToXmlWithReplace(Object obj, String path,String fileName,String typeId) {
        FileWriter fw = null;
        try {
            // 利用jdk中自带的转换类实现
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            StringWriter stringWriter = new StringWriter();
            stringWriter.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n    ");
            Marshaller marshaller = context.createMarshaller();
            // 格式化xml输出的格式
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                    Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            marshaller.marshal(obj,stringWriter);
            String stringXml = stringWriter.toString().replace("SCMBOT-TYPE-ID",typeId);
            // 将对象转换成输出流形式的xml
            // 创建输出流
            File destFile = new File(path);
            if(!destFile.exists()) {
                destFile.mkdirs();
            }
            fw = new FileWriter(path + File.separator + fileName + ".xml");
            fw.write(stringXml);
        } catch (JAXBException | IOException e) {
            log.error("生成xml文件异常",e);
            throw new ServiceException("生成报文异常");
        } finally {
            if (null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }



    /**
     * 将对象根据路径转换成xml文件并压缩，压缩文件名同原xml文件
     *
     * @param obj          需要转换的对象
     * @param path         路径
     * @param fileName    文件名，不含文件后缀
     * @return
     */
    public static void convertToXmlWithZip(Object obj, String path,String fileName) {
        FileWriter fw = null;
        try {
            // 利用jdk中自带的转换类实现
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            StringWriter stringWriter = new StringWriter();
            stringWriter.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n    ");
            Marshaller marshaller = context.createMarshaller();
            // 格式化xml输出的格式
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                    Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            marshaller.marshal(obj,stringWriter);
            String stringXml = stringWriter.toString();
            // 将对象转换成输出流形式的xml
            // 创建输出流
            File destFile = new File(path);
            if(!destFile.exists()) {
                destFile.mkdirs();
            }
            String absoluteFilePath = path + File.separator + fileName + ".xml";
            fw = new FileWriter(absoluteFilePath);
            fw.write(stringXml);
            fw.flush();
            //压缩文件
           ZipUtil.zip(new File(absoluteFilePath));
        } catch (JAXBException | IOException e) {
            log.error("生成xml文件异常",e);
            throw new ServiceException("生成报文异常");
        } finally {
            if (null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 将对象根据路径转换成xml文件并压缩，压缩文件名同原xml文件
     *
     * @param obj          需要转换的对象
     * @param path         路径
     * @param fileName    文件名，不含文件后缀
     * @param needReplace2Pre 替换成舱单
     * @return
     */
    public static void convertToXmlWithZipForManifest(Object obj, String path,String fileName,Boolean needReplace2Pre,String replaceVal) {
        FileWriter fw = null;
        try {
            // 利用jdk中自带的转换类实现
            JAXBContext context = JAXBContext.newInstance(obj.getClass());
            StringWriter stringWriter = new StringWriter();
            stringWriter.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "\n    ");
            Marshaller marshaller = context.createMarshaller();
            // 格式化xml输出的格式
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                    Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            marshaller.marshal(obj,stringWriter);
            String stringXml = stringWriter.toString();
            if(Objects.equals(needReplace2Pre,true)) {
                stringXml = stringXml.replace("urn:Declaration:datamodel:standard:CN:MT1401:1",replaceVal);
            }
            // 将对象转换成输出流形式的xml
            // 创建输出流
            File destFile = new File(path);
            if(!destFile.exists()) {
                destFile.mkdirs();
            }
            String absoluteFilePath = path + File.separator + fileName + ".xml";
            fw = new FileWriter(absoluteFilePath);
            fw.write(stringXml);
            fw.flush();
            //压缩文件
            ZipUtil.zip(new File(absoluteFilePath));
        } catch (JAXBException | IOException e) {
            log.error("生成xml文件异常",e);
            throw new ServiceException("生成报文异常");
        } finally {
            if (null != fw) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 将String类型的xml转换成对象
     */
    public static Object convertXmlStrToObject(Class clazz, String xmlStr) {
        Object xmlObject = null;
        try {
            JAXBContext context = JAXBContext.newInstance(clazz);
            // 进行将Xml转成对象的核心接口
            Unmarshaller unmarshaller = context.createUnmarshaller();
            StringReader sr = new StringReader(xmlStr);
            xmlObject = unmarshaller.unmarshal(sr);
        } catch (JAXBException e) {
           log.error("字符串xml转换成对象异常",e);
           throw new ServiceException("系统转换报文异常");
        }
        return xmlObject;
    }

    /**
     * 将file类型的xml转换成对象
     */
    public static Object convertXmlFileToObject(Class clazz, String xmlPath) {
        Object xmlObject = null;
        try {
            JAXBContext context = JAXBContext.newInstance(clazz);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            FileReader fr = null;
            fr = new FileReader(xmlPath);
            xmlObject = unmarshaller.unmarshal(fr);
        } catch (FileNotFoundException e1) {
            throw new ServiceException("文件不存在");
        } catch (JAXBException e2) {
            throw new ServiceException("文件转换成报文异常");
        }
        return xmlObject;
    }





}
